#include "sys/socket.h"
#include "netinet/in.h"
#include "stdio.h"
#include "string.h"
#include "errno.h"

#include "tcp_funs.h"

#define BUFSIZE 50

void process_msg_of_string(int conn_fd);
void process_msg_of_specificated_data(int conn_fd);

void tcp_server()
{
	  int socket_listen, conn_fd;
	  struct sockaddr_in server_addr, remote_addr;
	  int bind_ret_val, listen_ret_val, send_ret_val, recv_ret_val;
	  int sockaddr_len, send_len;


	  socket_listen = socket(PF_INET, SOCK_STREAM, 0);
	  if(-1 == socket_listen) {
		  printf("&tcp_server: fail to create socket, program exit.\n");
		  printf("&tcp_server: The failure reason is %d.\n", errno);
		  exit(0);
	  }

	  memset(&server_addr, 0, sizeof(server_addr));
	  server_addr.sin_family = AF_INET;
	  server_addr.sin_port = htons(8000);
	  server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

	  bind_ret_val = bind(socket_listen, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
	  if(-1 == bind_ret_val) {
		  printf("&tcp_server: fail to bind socket to local address, program exit.\n");
		  printf("&tcp_server: The failure reason is %d.\n", errno);
		  exit(0);
	  }

	  listen_ret_val = listen(socket_listen, 3);
	  if(-1 == listen_ret_val) {
			printf("&tcp_server: fail to listen on the socket, program exit.\n");
			printf("&tcp_server: The failure reason is %d.\n", errno);
			exit(0);
	  }

	  printf("Listenning to socket......\n");
	  sockaddr_len = sizeof(struct sockaddr);
	  conn_fd = accept(socket_listen,
			  (struct sockaddr*)&remote_addr, &sockaddr_len);
	  if(-1 == conn_fd) {
		  printf("tcp_server: fail to accept for clients, program exit.\n");
		  printf("&tcp_server: The failure reason is %d.\n", errno);
	  }

	  while(-1 != conn_fd) {
			printf("accepted a client.\n");

			send_len = strlen("Welcome you, this is server powered by mobile+.");
			send_ret_val = send(conn_fd, "Welcome you, this is server powered by mobile+.", send_len, 0);
			if(send_len != send_ret_val) {
			  printf("&tcp_server: fail to send welcome message from server, program exit.\n");
			  printf("&tcp_server: The failure reason is %d.\n", errno);
			  exit(0);
			}

			process_msg_of_specificated_data(conn_fd);

			close(conn_fd);
			printf("close the connection to client.\n");

			printf("Listenning to socket again......\n");
			conn_fd = accept(socket_listen, (struct sockaddr*)&remote_addr, &sockaddr_len);
			if(-1 == conn_fd) {
				printf("tcp_server: fail to accept for clients, program exit.\n");
				printf("&tcp_server: The failure reason is %d.\n", errno);
			 }
	  }

	  close(socket_listen);

	  return;
}

void process_msg_of_specificated_data(int conn_fd)
{
	int recv_ret_val;

	struct employee_t* p_employee = (struct employee_t*)malloc(sizeof(struct employee_t));
	if(NULL == p_employee) {
		printf("&tcp_server: fail to allocate memory, program exit.\n");
		exit(0);
	}


	while( 0 < (recv_ret_val = recv(conn_fd, (void*)p_employee, sizeof(struct employee_t), 0)) ) {
#ifdef DEBUG_TCP
		printf("&tcp_server: the return value of recv fun is :%d\n", recv_ret_val);
#endif
		printf("&tcp_server: the data received from remore address is described as below:\n");
		printf("&tcp_server: the name of this employee is: %s\n", p_employee->name);
		printf("&tcp_server: the age of this employee is %d\n", p_employee->age);
		printf("&tcp_server: the gender of this employee is %d\n", p_employee->gender);
		printf("&tcp_server: the employed year of this employee is %f\n", p_employee->employed_year);
		printf("&tcp_server: the salary of this employee is %f\n", p_employee->salary);
	}
	if(-1 == recv_ret_val) {
		printf("&tcp_server: fail to receive data from the client, program exit.\n");
		printf("&tcp_server: The failure reason is %d.\n", errno);
	}
	else if(0 == recv_ret_val) {
		printf("&tcp_server: the client has disconnect to server.\n");
	}
#if DEBUG_TCP
	printf("&tcp_server: the return value of recv fun is :%d\n", recv_ret_val);
#endif

	return;
}

void process_msg_of_string(int conn_fd)
{
	int recv_ret_val, send_ret_val;
	char recv_buf[BUFSIZE];

	while( 0 < (recv_ret_val = recv(conn_fd, recv_buf, BUFSIZE, 0)) ) {
#ifdef DEBUG_TCP
		printf("the return value of recv fun is :%d\n", recv_ret_val);
#endif
		recv_buf[recv_ret_val] = '\0';
		printf("&tcp_server: data reveived from remote address is: %s\n", recv_buf);
		send_ret_val = send(conn_fd, recv_buf, recv_ret_val, 0);
		if(recv_ret_val != send_ret_val) {
			printf("&tcp_server: fail to re-send data from remote, program exit.\n");
			printf("&tcp_server: The failure reason is %d.\n", errno);
			exit(0);
		}
	}
	if(-1 == recv_ret_val) {
		printf("&tcp_server: fail to receive data from the client, program exit.\n");
		printf("&tcp_server: The failure reason is %d.\n", errno);
	}
	else if(0 == recv_ret_val) {
		printf("tcp_server: the client has disconnect to server.\n");
	}
#if DEBUG_TCP
	printf("the return value of recv fun is :%d\n", recv_ret_val);
#endif

	return;
}
